#include <stdio.h>
#include <sys/file.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
#include <pthread.h>
#include "list.h"

//#define LOCK_LIST(l) pthread_mutex_lock(&(l->m_mutex))
//#define UNLOCK_LIST(l) pthread_mutex_unlock(&(l->m_mutex))

struct mr_listnode_s {
	struct mr_listnode_s *next;
	struct mr_listnode_s *prev;
	void *data;
	int datasize;
};

struct mr_list_s {
	
	mr_listnode_p first;
	mr_listnode_p last;
	int length;
	mr_list_data_free * freefunc ;
};

int mr_list_init(mr_list_p *plist ,mr_list_data_free freefunc){

	*(plist) = (mr_list_p)malloc(sizeof(mr_list_t));
	memset(*plist, 0, sizeof(mr_list_t));
	(*plist)->freefunc=freefunc;
	return  0;
}
int  mr_list_new_node(mr_listnode_p *pnode ,void *data,int datasize);
int mr_list_push(mr_list_p plist,void * data,int datasize)
{
	mr_listnode_p node;
	mr_list_new_node(&node,data,datasize);
	if( plist->first ) {
		plist->last->next = node;
		node->prev = plist->last;
		plist->last = node;
	}
	else {
		plist->first = plist->last = node;
	}
	++(plist->length);
//	pthread_cond_signal(&(plist->th_cond));
//	pthread_cond_broadcast(&(plist->th_cond));

	return 0;
}

int  mr_list_pop(mr_list_p plist,void **pdata,int * datasize){
	if( !plist->length )
		return -1;
	mr_listnode_p node;
	node = plist->first;
	(*pdata)=node->data;
	if( datasize )
		(*datasize)=node->datasize;
	plist->first=plist->first->next;
	if(plist->first != NULL )
		plist->first->prev = NULL;
	else
		plist->last = NULL;
	free(node);

	--plist->length;

	return 0;
}

int  mr_list_new_node(mr_listnode_p * pnode,void *data,int datasize) {

	*(pnode) = (mr_listnode_p)malloc(sizeof(mr_listnode_t));
	memset(*(pnode), 0, sizeof(mr_listnode_t));
	(*pnode)->data =data;
	(*pnode)->datasize = datasize;
//	free (data);
	return 0;
}


int mr_list_get_first(mr_listnode_p *pnode){
	
	return 0;
}
int mr_list_get_next(mr_list_p plist,mr_listnode_p *pnode,void **ppdata ){

	if( !ppdata )
		return -1;

	if(!plist->length) {
		if( pnode )
			*pnode = NULL;
		*ppdata = NULL;
		return -1;
	}
	if(*pnode==NULL) 
	{
		*pnode = plist->first;
		*ppdata = (*pnode)->data;
		return 0;
	}else
	{
		if((*pnode)->next!=NULL)
		{
			*pnode = (*pnode)->next;
			*ppdata = (*pnode)->data;
			return 0;
		}else {
			if( pnode )
				*pnode = NULL;
			*ppdata = NULL;
			return -1;
		}
	}

	return 0;
}

void mr_list_free(mr_list_p plist)
{
	mr_listnode_p pnode;
	mr_listnode_p pnext;

	if( !plist || !(pnode = plist->first) )
		return;

	do {
		pnext = pnode->next;
		if( plist->freefunc )
		{
			if(pnode->data)
				plist->freefunc(pnode->data);
		}
		free(pnode);
	} while( (pnode = pnext) );
}

int  mr_list_destroy(mr_list_p plist){
	// to do  
	// loop through all nodes and free every node
	mr_list_free(plist);
	free(plist);
	return 0;
}

int  mr_list_size(mr_list_p plist){

	return plist->length;
}

